ci: pass quote-capable outputs to the backport workflow shell via env vars - #13021
Merged
Conversation
… vars The "Save result to file" step interpolated the milestones result JSON inline into a single-quoted shell string, so any commit message containing an apostrophe broke the script (syntax error near unexpected token) and silently dropped the backport -- first triggered by #12985, whose title contains "aiohttp's". This is the third instance of the same defect class in this workflow (8bac288, #7405), and #7405 fixed only the jq-argument site while leaving this step and the author/labels interpolations behind. Route every quote-capable value (result JSON, author, author email, labels) through env vars, matching the pattern #7405 established for the commit message, and write the result file with printf instead of echo. Reproduced the exact failure payload against both patterns: the old one fails identically, the new one round-trips the JSON intact. Past apostrophe-titled PRs never hit this because their milestones were absent (or set only after merge), so the vulnerable payload stayed empty. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fregataa
approved these changes
Jul 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The backport workflow's "Save result to file" step interpolated the milestones result JSON inline into a single-quoted bash string:
Any commit message containing an apostrophe terminates the quote early and the step dies with
syntax error near unexpected token '('— first triggered by #12985 (title containsaiohttp's), which lost its automatic 26.4 backport.Why only now
The vulnerable payload only includes the commit message when a target branch was resolved at run time. Auditing all apostrophe-titled commits on main: #12898/#12638/#12278 had no milestone, and #11983's milestone was set 52 seconds after merge — so the payload stayed empty and the step passed. #12985 was the first apostrophe-titled PR with its milestone set before merge (per our new milestone discipline), which finally lit the latent bug. (Side finding: #11983 silently missed its 26.4 backport this way.)
History
Third instance of this defect class here:
8bac28817(hotfix: shell var-expansion), then #7405 moved the commit message into anenv:var for the jq arguments — but left this step and the author/labels interpolations behind.Changes
Following the same env-var pattern (#7405 / GitHub's workflow-injection guidance):
Save result to file: result JSON viaMILESTONES_RESULTenv +printf '%s'(no shell parsing of the payload)Get target branches: author / author-email / labels jq args via env varsCherry-pick:git config user.name/emailvia env varsVerification
syntax error near unexpected token '('; new → file round-trips, JSON parses, apostrophe intactAfter merge: re-dispatch the backport workflow for
b166f88b3(#12985) — and optionallyf30e32437(#11983, the silently-missed backport).🤖 Generated with Claude Code